<template>
  <div class="table-manager">
    <!-- 搜索表单 -->
    <div v-if="showSearch" class="search-form">
      <slot 
        name="search" 
        :search-form="searchForm" 
        :handle-search="handleSearch" 
        :handle-reset="handleReset"
        :loading="loading"
      />
    </div>

    <!-- 表格区域 -->
    <div class="table-container">
      <div class="table-header">
        <div class="table-title">{{ title }}</div>
        <div class="table-actions">
          <slot 
            name="actions" 
            :handle-add="handleAdd" 
            :handle-export="handleExport"
            :handle-import="handleImport"
            :handle-refresh="handleRefresh"
            :selected-rows="selectedRows"
            :loading="loading"
          />
        </div>
      </div>

      <!-- 数据表格 -->
      <el-table
        v-loading="loading"
        :data="tableData"
        style="width: 100%"
        @selection-change="handleSelectionChange"
        v-bind="tableProps"
      >
        <slot name="columns" :table-data="tableData" :handle-edit="handleEdit" :handle-delete="handleDelete" />
      </el-table>

      <!-- 分页 -->
      <el-pagination
        v-if="showPagination"
        v-model:current-page="pagination.pageNum"
        v-model:page-size="pagination.pageSize"
        :total="pagination.total"
        :page-sizes="pageSizes"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        class="pagination"
      />
    </div>

    <!-- 表单对话框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      :width="dialogWidth"
      :close-on-click-modal="false"
      @close="handleDialogClose"
    >
      <slot 
        name="form" 
        :form-data="formData" 
        :form-rules="formRules" 
        :form-ref="formRef"
        :is-edit="isEdit"
        :loading="submitLoading"
      />
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance } from 'element-plus'

// 定义组件属性
interface Props {
  title: string
  showSearch?: boolean
  showPagination?: boolean
  showActions?: boolean
  dialogWidth?: string
  pageSizes?: number[]
  tableProps?: Record<string, any>
}

const props = withDefaults(defineProps<Props>(), {
  showSearch: true,
  showPagination: true,
  showActions: true,
  dialogWidth: '600px',
  pageSizes: () => [10, 20, 50, 100],
  tableProps: () => ({})
})

// 定义事件
const emit = defineEmits<{
  search: [params: any]
  add: []
  edit: [row: any]
  delete: [row: any]
  export: []
  import: []
  refresh: []
  submit: [data: any, isEdit: boolean]
  selectionChange: [selection: any[]]
}>()

// 响应式数据
const loading = ref(false)
const submitLoading = ref(false)
const tableData = ref<any[]>([])
const selectedRows = ref<any[]>([])
const dialogVisible = ref(false)
const isEdit = ref(false)
const formRef = ref<FormInstance>()

// 搜索表单
const searchForm = reactive<Record<string, any>>({})

// 分页
const pagination = reactive({
  pageNum: 1,
  pageSize: 10,
  total: 0
})

// 表单数据
const formData = ref<Record<string, any>>({})
const formRules = ref<Record<string, any>>({})

// 计算属性
const dialogTitle = computed(() => isEdit.value ? '编辑' : '新增')

// 方法
const handleSearch = () => {
  pagination.pageNum = 1
  emit('search', { ...searchForm, ...pagination })
}

const handleReset = () => {
  Object.keys(searchForm).forEach(key => {
    searchForm[key] = ''
  })
  handleSearch()
}

const handleAdd = () => {
  isEdit.value = false
  formData.value = {}
  dialogVisible.value = true
  emit('add')
}

const handleEdit = (row: any) => {
  isEdit.value = true
  formData.value = { ...row }
  dialogVisible.value = true
  emit('edit', row)
}

const handleDelete = async (row: any) => {
  try {
    await ElMessageBox.confirm('确定要删除这条记录吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    emit('delete', row)
  } catch {
    // 用户取消删除
  }
}

const handleExport = () => {
  emit('export')
}

const handleImport = () => {
  emit('import')
}

const handleRefresh = () => {
  emit('refresh')
}

const handleSubmit = async () => {
  if (!formRef.value) return
  
  try {
    await formRef.value.validate()
    submitLoading.value = true
    emit('submit', formData.value, isEdit.value)
  } catch (error) {
    console.error('表单验证失败:', error)
  } finally {
    submitLoading.value = false
  }
}

const handleSelectionChange = (selection: any[]) => {
  selectedRows.value = selection
  emit('selectionChange', selection)
}

const handleSizeChange = (size: number) => {
  pagination.pageSize = size
  pagination.pageNum = 1
  emit('search', { ...searchForm, ...pagination })
}

const handleCurrentChange = (page: number) => {
  pagination.pageNum = page
  emit('search', { ...searchForm, ...pagination })
}

const handleDialogClose = () => {
  formRef.value?.resetFields()
  formData.value = {}
}

// 暴露方法给父组件
defineExpose({
  setTableData: (data: any[]) => {
    tableData.value = data
  },
  setPagination: (paginationData: { pageNum: number; pageSize: number; total: number }) => {
    Object.assign(pagination, paginationData)
  },
  setLoading: (loadingState: boolean) => {
    loading.value = loadingState
  },
  setSearchForm: (form: Record<string, any>) => {
    Object.assign(searchForm, form)
  },
  setFormRules: (rules: Record<string, any>) => {
    formRules.value = rules
  },
  closeDialog: () => {
    dialogVisible.value = false
  },
  refresh: handleRefresh
})
</script>

<style scoped lang="scss">
.table-manager {
  .search-form {
    background: #fff;
    padding: 20px;
    border-radius: 8px;
    margin-bottom: 20px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }

  .table-container {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    overflow: hidden;
  }

  .table-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px;
    border-bottom: 1px solid #ebeef5;

    .table-title {
      font-size: 16px;
      font-weight: 600;
      color: #303133;
    }

    .table-actions {
      display: flex;
      gap: 8px;
    }
  }

  .pagination {
    padding: 20px;
    text-align: right;
  }
}
</style>
